home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Experimental BBS Explossion 3
/
Experimental BBS Explossion III.iso
/
comunic
/
twft099b.zip
/
TWMAP.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-06-07
|
13KB
|
478 lines
Unit TwMap;
{
Copyright (C) 1993 by David Myers. All rights reserved. Personal
copying and use of this code permitted. This source cannot be
sold or distributed for more than the cost of media.
}
interface
uses
Crt,FlyCom,FParser,TwScr,TwBuffer,TwAnsi,TwLine,TwTrade,TwLaunch;
{ From TwLaunch: we have access to:
const
MaxSectors = 1000;
type
DistType = RECORD
Sector, Distance : Integer;
END;
SectorArray = ARRAY[1 .. MaxSectors] of byte;
MaxDistType = ARRAY[ 1 .. 25] of DistType;
var
MySectors : SectorArray;
MaxDist : integer;
MaxDistArray : MaxDistType;
}
Procedure ParseMap;
implementation
type
AdjList = ARRAY[1 .. MaxSectors, 1 .. 6] of integer;
AdjListPtr = ^AdjList;
MyQ = RECORD
Q: ARRAY[1 .. MaxSectors] of Integer;
head : integer;
tail : integer;
END;
Procedure InitList(var A : AdjListPtr);
BEGIN
new(A);
END;
Procedure TerminateList(var A : AdjListPtr);
BEGIN
dispose(A);
END;
{----- queue procedures (see Sedgewick, ALGORITHMS) -----}
Procedure InitQ(var Q : MyQ);
BEGIN
Q.head := 1;
Q.tail := 1;
END;
Procedure PutQ(var Q : MyQ; i : integer);
BEGIN
Q.Q[Q.tail] := i;
Inc(Q.tail);
If (Q.tail > MaxSectors) then
Q.tail := 1;
END;
Function GetQ(var Q : MyQ) : integer;
var
t : integer;
BEGIN
t := Q.Q[Q.head];
Inc(Q.head);
if (Q.head > MaxSectors) then
Q.head := 1;
GetQ := t;
END;
Function QEmpty(var Q : MyQ) : Boolean;
BEGIN
If (Q.head = Q.tail) then
QEMpty := TRUE
ELSE QEMpty := FALSE;
END;
{ ----- end queue procedures -----}
{ breadth first search, used to find distances on TW universe }
{ implemented on a FIFO queue, a la Sedgewick }
Procedure BFSVisit(node : integer; A : AdjListPtr; var V : SectorArray);
const
UNSEEN = 0;
var
i,t : integer;
dist : byte;
Q : MyQ;
BEGIN
InitQ(Q);
for i := 1 to 1000 do
V[i] := UNSEEN;
PutQ(Q,node);
V[node] := 255;
While (NOT QEmpty(Q)) do
BEGIN
node := GetQ(Q);
dist := V[node];
if (dist > 250) then
dist := 0;
for i := 1 to 6 do begin
t := A^[node][i];
if (t > 0) then begin
if (V[t] = UNSEEN) then begin
PutQ(Q,t);
V[t] := dist+1;
end;
end;
end;
END;
END;
{
routine for generating level diagrams as described by Woody Weaver
in the documentation file MAPPING.TXT
}
Procedure ParseMap;
label
TheEnd;
type
BoolArray = ARRAY[1 .. 1000] of Boolean;
var
A : AdjListPtr;
V : SectorArray;
i, j, k, index, ec1, toks, Root, X, Y : integer;
OldSector, NewSector : integer;
tokstr,ptok,inputstr,answer,S : string;
MyFile, MyName : string;
P : parsetype;
Loop, Done : Boolean;
Terminal : BoolArray;
isSct, SkipCIM,NewWarp : Boolean;
F : text;
BEGIN
InitList(A);
Loop := TRUE;
tokstr := ' '+#9+#8+#10+#13;
ptok := ' .'+#9+#8+#10+#13;
for i := 1 to 1000 do begin
Terminal[i] := TRUE;
V[i] := 0;
for j := 1 to 6 do
A^[i][j] := 0;
end;
SaveScreen(X,Y);
TextColor(LightCyan);
TextBackGround(Blue);
WFrameW(5,5,45,12);
ClrScr;
TextColor(Yellow);
Write(' What Root do you want? ');
TextColor(White);
ReadLn(Root);
TextColor(Yellow);
Write(' Skip CIM report Y/n? ');
TextColor(WHite);
ReadLn(Answer);
If (length(Answer) = 0) or (Answer[1] = 'Y') or (Answer[1] = 'y') then
SkipCIM := TRUE
else SkipCIM := FALSE;
TextColor(Yellow);
Write(' AST or SCT report A/s? ');
TextColor(White);
ReadLn(Answer);
If (length(Answer) = 0) or (Answer[1] = 'A') or (Answer[1] = 'a') then
isSCT := FALSE
else isSCT := TRUE;
WriteLn;
Write(' File Name : ');
BuildString(MyName);
toks := Parse_Str(ptok,MyName,P);
if (toks > 0) then
MyName := P.s[0]
ELSE MyName := 'LEVDIAG';
RestoreScreen;
SelectWindow(1);
TextColor(White);
TextBackground(Red);
ClrScr;
Write(' -----====== ALT-W Level Diagram Collection; ALT-Q Quits =====----- ');
SelectWindow(2);
NormalVideo;
GotoXY(X,Y);
Async_Send('C');
REPEAT
GetALine(toks,tokstr,inputstr,'?',P,Loop);
UNTIL ((NOT Loop) or MatchToken(P.s[toks-1],'?'));
If Loop and NOT SkipCIM then begin
Delay(1000);
Async_Send_String('╚╔╩╦╠═');
REPEAT
GetALine(toks,tokstr,inputstr,':',P,Loop);
UNTIL ((NOT Loop) or MatchToken(P.s[toks-1],':'));
If Loop then begin
Delay(1000);
Async_Send('I');
REPEAT
GetALine(toks,tokstr,inputstr,':',P,Loop);
if (Isdigit(P.s[0][1])) then begin
Val(P.s[0],index,ec1);
if ec1 = 0 then
for j := 1 to toks-1 do
Val(P.s[j],A^[index][j],ec1); { fill .SCT array }
end;
UNTIL ((NOT Loop) or MatchToken(P.s[toks-1],':'));
Delay(1000);
Async_Send('Q'); { out of CIM }
REPEAT
GetALine(toks,tokstr,inputstr,'?',P,Loop);
UNTIL ((NOT Loop) or MatchToken(P.s[toks-1],'?'));
end; { if Loop }
BFSVisit(Root,A,V);
end; {if Loop and NOT SkipCIM }
{ okay, ready for course plotting }
{ so calculate distances }
V[Root] := 255;
Terminal[Root] := FALSE;
for i := 1 to 1000 do
if V[i] > 0 then
Terminal[i] := FALSE;
j := 0;
While (j < 1000) do begin
Inc(j);
If ((V[j] = 0) and (J <> Root) and Terminal[j]) then begin
Async_Send('F');
REPEAT
GetALine(toks,tokstr,inputstr,'?',P,Loop);
UNTIL ((NOT Loop) or MatchToken(P.s[toks-1],'?'));
if Loop then begin
Str(Root,S);
S := S + #13;
Async_Send_String(S);
REPEAT
GetALine(toks,tokstr,inputstr,'?',P,Loop);
UNTIL ((NOT Loop) or MatchToken(P.s[toks-1],'sector?'));
if Loop then begin
Str(j,S);
S := S + #13;
Async_Send_String(S);
REPEAT
GetALine(toks,tokstr,inputstr,':',P,Loop);
UNTIL ((NOT Loop) or MatchToken(P.s[toks-1],'is:'));
if Loop then begin
NewWarp := False;
OldSector := 0;
REPEAT
GetALine(toks,tokstr,inputstr,' ?',P,Loop);
{ LastAttr is a global variable created by the ansi driver
to save the previous screen attributes }
If MatchToken(P.s[0],'>') then
NewWarp := TRUE
else begin
If isdigit(P.s[0][1]) then begin
if NewWarp then begin
NewWarp := False;
Val(P.s[0],NewSector,ec1);
if (ec1 = 0) then begin
if (OldSector > 0) then begin
Terminal[OldSector] := FALSE;
k := 1;
Done := FALSE;
While ((k < 7) and NOT Done) do begin
if (A^[OldSector][k] = 0) then
Done := TRUE
else if (A^[OldSector][k] = NewSector) then begin
Done := TRUE;
k := 7;
end
else begin
Inc(k);
if (k > 6) then
Done := TRUE;
end;
end;
If (k < 7) then
A^[OldSector][k] := NewSector;
end; { OldSector > 0}
OldSector := NewSector;
end;
end
else begin
Val(P.s[0],NewSector,ec1);
If (ec1 = 0) then
OldSector := NewSector
else OldSector := 0;
end;
end; { if Isdigit.. }
If MatchToken(P.s[toks-1],'Avoids?') then begin
{ this "if" should work but it doesn't..}
Delay(2500);
Async_Send('N');
Async_Send(#13);
end;
end; { else MatchToken to '>' }
UNTIL ((NOT Loop) or MatchToken(P.s[toks-1],'?'));
if Loop then begin { #4 }
{ do nothing so far .. }
end; { loopit #4 }
end; { loopit #3 }
end; { loopit #2 }
end; { loopit #1 }
end;
end;
{ end of root ---> sector paths }
if NOT Loop then
goto TheEnd;
j := 0;
While (j < 1000) do begin
Inc(j);
If Terminal[j] and (J <> Root) then begin
Async_Send('F');
REPEAT
GetALine(toks,tokstr,inputstr,'?',P,Loop);
UNTIL ((NOT Loop) or MatchToken(P.s[toks-1],'?'));
if Loop then begin
Str(J,S);
S := S + #13;
Async_Send_String(S);
REPEAT
GetALine(toks,tokstr,inputstr,'?',P,Loop);
UNTIL ((NOT Loop) or MatchToken(P.s[toks-1],'sector?'));
if Loop then begin
Str(Root,S);
S := S + #13;
Async_Send_String(S);
REPEAT
GetALine(toks,tokstr,inputstr,':',P,Loop);
UNTIL ((NOT Loop) or MatchToken(P.s[toks-1],'is:'));
if Loop then begin
NewWarp := False;
OldSector := 0;
REPEAT
GetALine(toks,tokstr,inputstr,' ?',P,Loop);
{ LastAttr is a global variable created by the ansi driver
to save the previous screen attributes }
If MatchToken(P.s[0],'>') then
NewWarp := TRUE
else begin
If isdigit(P.s[0][1]) then begin
if NewWarp then begin
NewWarp := False;
Val(P.s[0],NewSector,ec1);
if (ec1 = 0) then begin
if (OldSector > 0) then begin
k := 1;
Done := FALSE;
While ((k < 7) and NOT Done) do begin
if (A^[OldSector][k] = 0) then
Done := TRUE
else if (A^[OldSector][k] = NewSector) then begin
Done := TRUE;
k := 7;
end
else begin
Inc(k);
if (k > 6) then
Done := TRUE;
end;
end;
If (k < 7) then
A^[OldSector][k] := NewSector;
end; { OldSector > 0}
OldSector := NewSector;
end;
end
else begin
Val(P.s[0],NewSector,ec1);
If (ec1 = 0) then
OldSector := NewSector
else OldSector := 0;
end;
end; { if Isdigit.. }
If MatchToken(P.s[toks-1],'Avoids?') then begin
{ this "if" should work but it doesn't..}
Delay(2500);
Async_Send('N');
Async_Send(#13);
end;
end; { else MatchToken to '>' }
UNTIL ((NOT Loop) or MatchToken(P.s[toks-1],'?'));
if Loop then begin { #4 }
{ do nothing so far .. }
end; { loopit #4 }
end; { loopit #3 }
end; { loopit #2 }
end; { loopit #1 }
end;
end;
Async_Send('Q');
TheEnd:
BFSVisit(Root,A,V);
{
set this up to write either a .SCT report or a more compact
.AST report
}
if isSct then begin
MyFile := MyName + '.SCT';
Assign(F,MyFile);
Rewrite(F);
WriteLn(F);
WriteLn(F);
for i := 1 to 1000 do begin
Write(F,i:4);
if (A^[i][1] = 0) then
WriteLn(F,' 0')
else begin
j := 1;
While (j < 7) and (A^[i][j] <> 0) do begin
Write(F,A^[i][j]:5);
Inc(j);
end;
WriteLn(F);
end;
WriteLn(F);
end;
WriteLn(F);
WriteLn(F);
WriteLn(F,':');
Close(F);
{ end of .SCT support }
end
else begin
MyFile := MyName + '.AST';
Assign(F,MyFile);
Rewrite(F);
WriteLn(F,':');
for i := 1 to 1000 do begin
Write(F,i:4);
if (A^[i][1] = 0) then
WriteLn(F,' 0')
else begin
j := 1;
While (j < 7) and (A^[i][j] <> 0) do begin
Write(F,A^[i][j]:5);
Inc(j);
end;
WriteLn(F);
end;
end;
WriteLn(F);
WriteLn(F,': ENDINTERROG');
Close(F);
{ end of .AST support }
end;
{ writing a .DIS file }
MyFile := MyName + '.DIS';
Assign(F,MyFile);
ReWrite(F);
for i := 1 to 1000 do begin
if V[i] > 200 then
WriteLn(F,i:4,' -1')
else
WriteLn(F,i:4,V[i]:5);
end;
Close(F);
{ writing a .EXT file }
MyFile := MyName + '.EXT';
Assign(F,MyFile);
ReWrite(F);
for i := 1 to 1000 do begin
if Terminal[i] then
WriteLn(F,i:4)
end;
Close(F);
{ TheEnd: }
TopLine;
TerminateList(A);
END;
END.